#!/user/bin/env python3
# -*- coding: utf-8 -*-
"""
--------------------------------------
    Author:     JiChao_Song
    Date  :     2020/12/22 09:05
    Desc  :     用例发送请求
--------------------------------------
"""
from common.libs.SimpleRequestsUtils import SimpleRequesUtils
from servers.models.ApiCaseModel import ApiCase
from servers.servers.HeadersServices import get_headers_dict
from servers.servers.VariableServices import get_veriable_by_name, add_veriable
from servers.servers.ProjectServices import get_project_by_id
from common.libs.FakerUtils import *
import jsonpath


def ApiCaseIsExist(id: str):
    """
    判断接口用例是否存在
    :param id:
    :return:
    """
    apicase = ApiCase.objects(id = id)

    if apicase.count() == 0:
        return {
            '_id': id,
            'apiNum': None,
            'apiName': None,
            'apiParam': None,
            'apiMethod': None,
            'apiPath': None,
            'apiHeader': None,
            'apiExtract': None,
            'apiAssert': None,
            'runCount': None,
            'response': [{"result": f'{id}不存在'}],
            'isRun': None,
            'isHeader': None,
        }

    return apicase.first()


class CaseRequestUtils:
    """
    用例发送请求类

    执行顺序(请求一次的逻辑)
    1. 发送请求
        1.1 构造请求参数
        1.2 构造请求头
        1.3 构造请求地址
    2. 断言结果
    3. 断言成功提取参数
        3.1 提取参数后保存到自定义变量中(Veriable)
    4. 返回结果
    """

    def __init__(self, apicase: ApiCase):

        self.apicase = apicase

        # 响应结果
        self.response = []

        # 情趣方法
        self.methods = self.apicase.apiMethod

        # 项目
        self.project = get_project_by_id(self.apicase.projectId)

        # 断言结果
        self.apiAssert = False

        # 用例总数
        self.caseAll = self.apicase.runCount
        # 通过数量
        self.casePass = 0
        # 失败数量
        self.caseFail = 0
        # 错误数量
        self.caseError = 0
        # 跳过数量
        self.caseSkip = 0

    def set_apiParam(self):
        """
        构造请求参数
        :return:
        """
        # 请求参数
        data = {}
        if self.apicase.apiParam and len(self.apicase.apiParam) != 0:
            for i in self.apicase.apiParam:
                value = i.get('value')
                # 判断value的值必须为str
                if isinstance(value, str):
                    # 1. 判断是否使用变量  2. 判断是否是内置函数
                    if '$' in value and 'random' in value:
                        index = value.index('$')
                        data[i.get('key')] = f'{value[:index]}{eval(value[index + 1:])}'
                        # 3. 使用自定义变量
                    elif '$' in value:
                        index = value.index('$')
                        data[i.get('key')] = f'{value[:index]}{get_veriable_by_name(variableName = value[index + 1:], projectId = self.apicase.projectId)}'
                    else:
                        data[i.get('key')] = value
                else:
                    data[i.get('key')] = value
        return data

    def set_apiHeaders(self):
        """
        设置请求头
        :return:
        """
        # 如果需要请求头并且项目存在
        if self.apicase.isHeader:
            return get_headers_dict(projectId = self.apicase.projectId)
        return None

    def set_apiAccess(self, request):
        """
        断言结果
        :return:
        """
        if self.apicase.apiAssert and request:
            code = jsonpath.jsonpath(request.json(), f'$..{self.apicase.apiAssert.get("key")}')[0]
            if str(code) == self.apicase.apiAssert.get('value'):
                self.apiAssert = True

    def set_apiExtract(self, request):
        """
        设置提取变量的值,并保存到自定义变量中
        :return:
        """
        if self.apiAssert and self.apicase.apiExtract and len(self.apicase.apiExtract) > 0:
            for i in self.apicase.apiExtract:
                variableValue = jsonpath.jsonpath(request.json(), f'$..{i}')[0]
                add_veriable(variableName = i, variableValue=str(variableValue), projectId = self.apicase.projectId)

    def ones_request(self, baseUrl: str):
        """
        构造一次请求
        :return:
        """
        data = self.set_apiParam()
        url = baseUrl + self.apicase.apiPath
        headers = self.set_apiHeaders()
        results = SimpleRequesUtils(methods = self.methods, url = url, data = data,
                                    headers = headers)

        res = results.send_requests()
        self.set_apiAccess(res)
        self.set_apiExtract(res)
        self.casePass += 1
        return results.dictResult()


    def dictResult(self):
        """
        构造返回结果

        :return:
        """
        simpleResule = {

            # test
        }
        pass

    def result(self):
        # 1.判断该条用例是否执行 并且判断该项目是否存在
        if self.apicase.isRun:
            if self.project:
                for i in range(self.apicase.runCount):
                    try:
                        result = dict(id = i + 1, result = self.ones_request(self.project.projectUrl))
                        self.response.append(result)
                    except:
                        self.caseFail += 1
            else:
                self.caseError += self.caseAll
        else:
            self.caseSkip += self.caseAll
        self.apicase.response = self.response
        return self.apicase.dict_json()
